﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace VS.Infrastructure.Controls
{
    public class SpeedSampler
    {
        /// <summary>
        /// Gets or sets the direction.
        /// </summary>
        /// <value>The direction.</value>
        public int Direction { get; set; }
        /// <summary>
        /// Gets or sets the speed.
        /// </summary>
        /// <value>The speed.</value>
        public double Speed { get; set; }
        /// <summary>
        /// Gets or sets the last ticks.
        /// </summary>
        /// <value>The last ticks.</value>
        private long LastTicks { get; set; }
        /// <summary>
        /// Gets or sets the last value.
        /// </summary>
        /// <value>The last value.</value>
        public double LastValue { get; set; }
        /// <summary>
        /// Gets or sets the last speed.
        /// </summary>
        /// <value>The last speed.</value>
        public double LastSpeed { get; set; }
        /// <summary>
        /// Gets or sets the max speed.
        /// </summary>
        /// <value>The max speed.</value>
        public double MaxSpeed { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="SpeedSampler"/> class.
        /// </summary>
        public SpeedSampler(double maxSpeed)
        {
            this.MaxSpeed = maxSpeed;
            this.Direction = 0;
            this.Speed = 0;
            this.LastTicks = 0;
            this.LastValue = 0;
        }

        /// <summary>
        /// Starts the specified value.
        /// </summary>
        /// <param name="value">The value.</param>
        public void Start(double value)
        {
            this.Direction = 0;
            this.Speed = 0;
            this.LastTicks = DateTime.Now.Ticks;
            this.LastValue = value;
        }

        /// <summary>
        /// Samples the specified value.
        /// </summary>
        /// <param name="value">The value.</param>
        public void Sample(double value)
        {
            this.Direction = Math.Sign(value - this.LastValue);
            this.LastSpeed = this.Speed;
            this.Speed = ComputeSpeed(value);
            this.LastTicks = DateTime.Now.Ticks;
            this.LastValue = value;
        }

        /// <summary>
        /// Computes the speed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private double ComputeSpeed(double value)
        {
            double distance = Math.Abs(value - this.LastValue);
            long time = DateTime.Now.Ticks - this.LastTicks;
            double speed = (distance / time * 10000000);
            return double.IsNaN(speed) ? 0 : speed;
        }

        /// <summary>
        /// Gets the speed.
        /// </summary>
        /// <returns></returns>
        public double GetSpeed()
        {
            double speed = (this.LastSpeed + this.Speed) / 2;
            return (speed > this.MaxSpeed ? this.MaxSpeed : speed);
        }
    }
}
